package com.example.shardingjdbc.shardingJdbcConfig;

import com.google.common.collect.Range;
import org.apache.shardingsphere.sharding.api.sharding.standard.PreciseShardingValue;
import org.apache.shardingsphere.sharding.api.sharding.standard.RangeShardingValue;
import org.apache.shardingsphere.sharding.api.sharding.standard.StandardShardingAlgorithm;
import org.springframework.stereotype.Component;

import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * @author ipc
 */
@Component
public class DatePreciseShardingAlgorithm implements StandardShardingAlgorithm<Date> {

    @Override
    public String doSharding(Collection<String> collection, PreciseShardingValue<Date> preciseShardingValue) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        String tableName = "jy_" + sdf.format(preciseShardingValue.getValue());
        if (collection.contains(tableName)) {
            return tableName;
        }
        throw new IllegalArgumentException("未找到匹配的数据表");
    }

    @Override
    public Collection<String> doSharding(Collection<String> collection, RangeShardingValue<Date> rangeShardingValue) {
        // 获取逻辑表名:jy
        String dbName = rangeShardingValue.getLogicTableName();

        // 获取分片键值对的取值范围
        Range<Date> valueRange = rangeShardingValue.getValueRange();

        // 使用Java8中的日期时间API获取开始时间和结束时间的LocalDate对象
        LocalDate startDate = valueRange.lowerEndpoint().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        LocalDate endDate = valueRange.upperEndpoint().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();

        // 计算出这【startDay~endDay】日期之间的所有日期,同时转换成对应数据库表名
        Set<String> res = new HashSet<>();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
        LocalDate currentDate = startDate;
        try {
            while (!currentDate.isAfter(endDate)) {
                res.add(dbName + "_" + currentDate.format(formatter));
                currentDate = currentDate.plusDays(1);
            }
        } catch (Exception e) {
            throw new RuntimeException("分片计算失败", e);
        }

        return res;
    }

    @Override
    public void init() {

    }

    @Override
    public String getType() {
        return "DatePreciseShardingAlgorithm";
    }
}
